#include "dbf_file.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <boost/algorithm/string.hpp>

const int HEAD_LEN = sizeof(DBF_HEAD);
const int FIELD_LEN = sizeof(DBF_FIELD);

dbf_reader::dbf_reader(const char *buf, unsigned int size)
{
	m_record_size = 0;
	m_record_count = reader(buf, size);
}

dbf_reader::~dbf_reader()
{

}

int dbf_reader::get_field_index_by_name(const char *field_name)
{
	int index = -1;
	string name(field_name);
	boost::algorithm::to_upper(name);

	field_index_map::iterator it = field_index.find(name);
	if (it != field_index.end())
	{
		index = it->second;
	}

	return index;
}

void dbf_reader::get_field_value(int record_index, int field_index)
{
	if (field_index < 0 || field_index > (int)m_field_descriptors.size())
		return ;

	offset_length &ol = field_ol_vector[field_index];

	char buf[265];
	memset(buf, 0, 265);
	memcpy(buf, m_records + record_index * m_record_size + ol.first, ol.second);
	buf[ol.second] = '\0';
	int i = 0;
	int j = 0;
	for (i = 0; i < ol.second; i++)
	{
		if (buf[i] == ' ')
			continue;
		m_result[j] = buf[i];
		j++;
		if (buf[i] == '\0')
			break;
	}

	m_result[j] = '\0';
}

void dbf_reader::get_field_value(int record_index, int field_index, char *value)
{
	get_field_value(record_index, field_index);
	strncpy(value, m_result, strlen(m_result));
	value[strlen(m_result)] = '\0';
}

void dbf_reader::get_field_value(int record_index, int field_index, long& value)
{
	get_field_value(record_index, field_index);
	value = atol(m_result);
}

void dbf_reader::get_field_value(int record_index, int field_index, unsigned long& value)
{
	get_field_value(record_index, field_index);
	value = atol(m_result);
}

void dbf_reader::get_field_value(int record_index, int field_index, int& value)
{
	get_field_value(record_index, field_index);
	value = atoi(m_result);
}

void dbf_reader::get_field_value(int record_index, int field_index, float& value)
{
	get_field_value(record_index, field_index);
	value = (float)atof(m_result);
}

void dbf_reader::get_field_value(int record_index, int field_index, double& value)
{
	get_field_value(record_index, field_index);
	value = atof(m_result);
}

char dbf_reader::get_version()
{
	return m_head.vers;
}

int dbf_reader::get_head_size()
{
	return m_head.header_size;
}

int dbf_reader::get_update()
{
	int today = (m_head.ymd[0] + 1900) * 10000 + m_head.ymd[1] * 100 + m_head.ymd[2];

	return today;
}

unsigned int dbf_reader::get_record_count()
{
	return m_record_count;
}

unsigned int dbf_reader::get_record_size()
{
	return m_record_size;
}

unsigned int dbf_reader::get_field_count()
{
	return m_field_descriptors.size();
}

void dbf_reader::reset_fields()
{
	field_ol_vector.clear();
	field_index.clear();

	unsigned int offset = 0;
	unsigned char length = 0;

	for (unsigned int i = 0; i < m_field_descriptors.size(); i++)
	{
		string name(m_field_descriptors[i].field_name);
		length = m_field_descriptors[i].field_length;
		offset = m_field_descriptors[i].field_offset;
		field_ol_vector.push_back(make_pair(offset, length));
		field_index.insert(make_pair(name, i));
/*		cout << "name " << name;
		cout << "\toffset " << offset;
		cout << "\tlength " << (int)length << endl;
*/	}
}

unsigned int dbf_reader::reader(const char *buf, unsigned int size)
{
	if (buf == NULL || strlen(buf) == 0)
		return 0;

	if (size < HEAD_LEN + FIELD_LEN)
		return 0;

	memcpy((void *)&m_head, buf, HEAD_LEN);

	if (m_head.header_size + m_head.record_counts * m_head.record_size > size)
		return 0;

	if (buf[m_head.header_size - 1] != 0x0d)	//头结束标志
		return 0;

	int field_count = (m_head.header_size - HEAD_LEN - 1) / FIELD_LEN;

	for (int i = 0; i < field_count; i++)
	{
		DBF_FIELD *pfield = (DBF_FIELD *)(buf + HEAD_LEN + i * FIELD_LEN);
		DBF_FIELD field;
		memcpy((void *)&field, pfield, FIELD_LEN);
		m_field_descriptors.push_back(field);
	}

	m_records = buf + m_head.header_size;
	m_record_count = m_head.record_counts;
	m_record_size = m_head.record_size;

	reset_fields();

	return m_record_count;
}

